// Follows guide from dreamincode.net/forums/topic/148707-introduction-to-using-libusb-10/

#include </usr/include/libusb-1.0/libusb.h>
#include <iostream> 
#include <stdint.h>

#define XB_VID	0x0403
#define XB_PID	0x6001

using namespace std; 
int main(int argc, char ** argv)
{
	
	libusb_device **devArr;
	libusb_device_handle *dev_handle;			// Handle for device
	libusb_context *ctx = NULL; 				// Session context
	
	int retVal;	// stores return values of funcs
	ssize_t count;	// Holds number of devices in dev list
	
	retVal = libusb_init(&ctx);	// Inits libusb session 
	
	if(retVal < 0){
		cout << "Initialization Error " << retVal << endl;	// Prints err
	}
	
	libusb_set_debug(ctx, 3);	// Sets verbosity to 3 (idk why)
	
	count = libusb_get_device_list(ctx, &devArr);	// Gets list of devices
	if(count < 0){
		cout << "Get Device Error " << count << endl; 
	}
	
	cout << count << " Devices in list." << endl; 

	dev_handle = libusb_open_device_with_vid_pid(ctx, XB_VID, XB_PID);	// Gets handle using XBee's vid and pid
	if(dev_handle == NULL){
		cout << "Cannot open device" << endl; 
	}else{
		cout << "Device Opened" << endl; 
	}
	
	libusb_free_device_list(devArr, 1);	// Frees array I guess?

	if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attach
        	cout<<"Kernel Driver Active"<<endl;
        	if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
            		cout<<"Kernel Driver Detached!"<<endl;
    	}
 
	
	retVal = libusb_claim_interface(dev_handle, 0);	// Use this to claim the dev interface
	if(retVal < 0){
		cout << "Error claiming the device: " << retVal << endl; 
		return -1; 
	}
	
	//unsigned char outBuff[] = "Hey"; // Buffer to hold outgoing data
	int32_t tChar = 0xFFFC61FF;

	int actualSent = 0;	// Actual num of bytes sent
	for(int i=0; i<100000000; i++){
		retVal = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), (unsigned char*)&tChar, 4, &actualSent, 200); 
		if(retVal == 0 && actualSent == 4){
			cout << "Write was a success!" << endl; 
		}else{
			cout << "ERROR Writing!" << endl; 
		}
	}
	/*	
	for(int i=0; i<10; i++){
		retVal = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_IN), outBuff, 3, &actualSent, 200); 
		if(retVal == 0 && actualSent == 3){
			cout << "Read: " << outBuff << endl; 
		}else{
			cout << "ERROR Writing!" << endl; 
		}
	}
	*/
	retVal = libusb_release_interface(dev_handle, 0); 
	if(retVal != 0){
		cout << "Error Releasing interface" << endl; 
	}else{
		cout << "Interface released successfully" << endl; 
	}
	
	libusb_close(dev_handle); 
	libusb_exit(ctx); 


	

	return 0; 
}	

